<template>
  <div
    class="model-class"
    v-loading="loading"
    element-loading-text="加载模型中"
    element-loading-spinner="el-icon-loading"
    element-loading-background="rgba(25, 44, 76, 0.8)"
    ref="threeContainer"
    id="threeContainer"
  ></div>
</template>

<script>
import * as THREE from "three";
import { FBXLoader } from "three/examples/jsm/loaders/FBXLoader.js";
import { GLTF, GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";

import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";

export default {
  name: "ThreeModel",
  props: {
    path: {
      type: String,
      default: "",
    },
    type:{
      type: String,
      default: "fbx",
    },
    initFun: {
      type: Function,
      default: () => {
        console.info("初始加载");
      },
    },
  },
  data() {
    return {
      loading: false,
      scene: null,
      camera: null,
      renderer: null,
    };
  },
  watch: {
    path:{
      deep: true,
      handler(newVal,oldVal) {
        if(newVal!=oldVal){
          document.getElementById('threeContainer').innerHTML = "";
          this.initThree();
        }
      },
    }
  },
  mounted() {
    if (this.path) this.initThree();
  },
  methods: {
    initThree() {
      this.loading = true;
      const width = this.$refs.threeContainer.clientWidth;
      const height = this.$refs.threeContainer.clientHeight;

      this.scene = new THREE.Scene();
      const model = new THREE.Group(); //声明一个组对象，用来添加加载成功的三维场景
      let that = this;
      let loader = new FBXLoader(); //创建一个GLTF加载器
      if(this.type == 'glb'){
        loader = new GLTFLoader()
      }

      loader.load(this.path, function (obj) {
        // obj.rotation.x = Math.PI / 2
        // obj.rotation.y = Math.PI / 1
        // obj.rotation.z = Math.PI / 1
        if(that.type == 'glb'){
          obj.scene.position.z = 60
          obj.scene.position.x = -7
          model.add(obj.scene); //三维场景添加到model组对象中
        }else{
          model.add(obj); //三维场景添加到model组对象中

        }
        that.animate();
        that.loading = false;
      });
      this.scene.add(model); //模型对象添加到场景中

      //辅助观察的坐标系
      // const axesHelper = new THREE.AxesHelper(100);
      // this.scene.add(axesHelper);

      //光源设置
      const directionalLight = new THREE.DirectionalLight(0xffffff, 10);
      directionalLight.position.set(400, 200, 300);
      this.scene.add(directionalLight);
      const ambient = new THREE.AmbientLight(0xffffff, 5);
      this.scene.add(ambient);

      this.camera = new THREE.PerspectiveCamera(30, width / height, 1, 3000);
      this.camera.position.set(0, 10, -50); //根据渲染范围尺寸数量级设置相机位置
      this.camera.lookAt(0, 0, 0);
      this.renderer = new THREE.WebGLRenderer();
      this.renderer.setSize(width, height);
      this.renderer.outputEncoding = THREE.sRGBEncoding;

      this.$refs.threeContainer.appendChild(this.renderer.domElement);
      this.initSky(); //设置背景
      window.addEventListener("resize", this.onWindowResize, false);

      // 设置相机控件轨道控制器OrbitControls
      const controls = new OrbitControls(this.camera, this.renderer.domElement);
      // 如果OrbitControls改变了相机参数，重新调用渲染器渲染三维场景
      controls.addEventListener("change", function () {
        console.info(this.camera)
        this.renderer.render(this.scene, this.camera); //执行渲染操作
      }); //监听鼠标、键盘事件
    },
    onWindowResize() {
      this.camera.aspect =
        this.$refs.threeContainer.clientWidth /
        this.$refs.threeContainer.clientHeight;
      this.camera.updateProjectionMatrix();
      this.renderer.setSize(
        this.$refs.threeContainer.clientWidth,
        this.$refs.threeContainer.clientHeight
      );
    },

    animate() {
      this.renderer.render(this.scene, this.camera);
      requestAnimationFrame(this.animate);
    },
    async initSky() {
      const path = "/images/";
      const urls = [
        path + "posx.jpg",
        path + "negx.jpg",
        path + "posy.jpg",
        path + "negy.jpg",
        path + "posz.jpg",
        path + "negz.jpg",
      ];
      const textCube = new THREE.CubeTextureLoader().load(urls);
      this.scene.background = textCube;
    },
  },
  beforeDestroy() {
    window.removeEventListener("resize", this.onWindowResize, false);
    this.$refs.threeContainer.removeChild(this.renderer.domElement);
  },
};
</script>

<style lang="scss">
.model-class {
  .el-loading-spinner .el-loading-text {
    color: #01f7fd;
  }
  .el-loading-spinner i {
    color: #01f7fd;
  }
}

/* 样式按需添加 */
</style>
